/*
 * Copyright (c) 2018. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
 * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan.
 * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna.
 * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus.
 * Vestibulum commodo. Ut rhoncus gravida arcu.
 */

package com.gov.dna.base.service.impl;


import com.gov.dna.base.entity.BaseNode;
import com.gov.dna.base.mapper.BaseNodeMapper;
import com.gov.dna.base.mybatis.BasePage;
import com.gov.dna.base.mybatis.BaseQuery;
import com.gov.dna.base.service.BaseNodeService;
import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 节点基础类 用于处理子父层级
 * @author (作者) Dong Jie 154046519@qq.com
 * @version V1.0
 * @date 2018/12/7 11:12
 * @since (该版本支持的JDK版本) 1.8
 */
public class BaseNodeServiceImpl<M extends BaseNodeMapper<T>,T extends BaseNode> extends BaseServiceImpl<M,T> implements BaseNodeService<T> {

    @Override
    public boolean insert(T entity) {
        entity.setNodeCode(buildCode(entity));
        return super.insert(entity);
    }

    /**
     * 创建编码
     * @author (作者) Dong Jie 154046519@qq.com
     * @param o
     * @return java.lang.String
     * @date 2019/1/6 16:09
     */
    private String buildCode(T o){
        try {
            if(o.getNodeFatherId()==null){
                o.setNodeFatherId(0L);
            }
            T temp= (T) o.getClass().newInstance();
            temp.setNodeFatherId(o.getNodeFatherId());
            List<T> rl=find(temp);
            if(rl!=null&&rl.size()>0){
                Long code=getMaxCode(rl);
                return String.format("%0" + rl.get(0).getNodeCode().length() + "d", code+1);
            }else{
                if(o.getNodeFatherId().equals(0L)){
                    return "001";
                }else{
                    T father=selectById(o.getNodeFatherId());
                   return father.getNodeCode()+"001";
                }
            }
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return "";
    }

    /**
     * 获得最大编码
     * @author (作者) Dong Jie 154046519@qq.com
     * @param list
     * @return java.lang.Long
     * @date 2019/1/6 16:03
     */
    private Long getMaxCode(List<T> list){
        Long result=1L;
        for(T t:list){
            if(StringUtils.isNumeric(t.getNodeCode())&&Long.valueOf(t.getNodeCode())>result){
                result=Long.valueOf(t.getNodeCode());
            }
        }
        return result;
    }

    @Override
    public List<T> buildTree(T o) throws InstantiationException, IllegalAccessException {
        BaseQuery<T> query=new BaseQuery<T>();
        query.setOrderByField("nodeFatherId,orderNum");
        query.setAsc(true);
        List<T> list=find(o,query);
        List<T> complete=completeList(list,o);
       return buildTree(complete,false);
    }

    /**
     * 将缺少的父级补充完整
     * @author (作者) Dong Jie 154046519@qq.com
     * @param list
     * @param o 直到补齐到父级id=o的父级id
     * @return java.util.List<T>
     * @date 2019/1/6 19:39
     */
    private List<T> completeList(List<T> list,T o) throws InstantiationException, IllegalAccessException {
        if(null!=list){
            Map<Long,T> map=new HashMap<Long,T>();
            map.put(0L,o);
            for(T t:list){
                map.put(t.getId(),t);
            }
            List<T> complete=new ArrayList<T>();
            for(T t:list){
                complete.add(t);
                addFather(t,map,complete,o);
            }
            return complete;
        }
        return list;
    }


    /**
     * 构建树形结构
     * @author (作者) Dong Jie 154046519@qq.com
     * @param list
     * @param isLazyMode 是否是懒加载模式
     * @return java.util.List<T>
     * @date 2019/1/6 19:49
     */
    private List<T> buildTree(List<T> list,Boolean isLazyMode) throws IllegalAccessException, InstantiationException {
        if (list == null || list.size() <= 1) {
            return list;
        }
        List<T> re = new ArrayList<T>();
        for (T p : list) {
            if (p.getNodeFatherId() == null || p.getNodeFatherId().equals(0L)) {
                List<T> ja = getChild(p, list,isLazyMode);
                if (ja != null && ja.size() > 0) {
                    p.setIsLeaf(false);
                    p.setChildren(ja);
                }else{
                    p.setIsLeaf(true);
                    if(isLazyMode&&!isLeaf(p)){
                        p.setIsLeaf(false);
                    }
                }
                re.add(p);
            }
        }
        return re;
    }


    /**
     * 获得子集
     * @author (作者) Dong Jie 154046519@qq.com
     * @param parent
     * @param list
     * @param isLazyMode 是否是懒加载模式
     * @return java.util.List<T>
     * @date 2019/1/6 19:49
     */
    public List<T> getChild(T parent, List<T> list,boolean isLazyMode) throws InstantiationException, IllegalAccessException {
        List<T> re = new ArrayList<T>();
        for (T p : list) {
            if (p.getNodeFatherId().equals(parent.getId())) {
                List<T> ps = getChild(p, list,isLazyMode);
                if (ps != null && ps.size() > 0) {
                    p.setIsLeaf(false);
                    p.setChildren(ps);
                }else{
                    p.setIsLeaf(true);
                    if(isLazyMode&&!isLeaf(p)){
                        p.setIsLeaf(false);
                    }
                }
                re.add(p);
            }
        }
        return re;
    }

    /**
     * 数据库中判断是否是叶子节点
     * @author (作者) Dong Jie 154046519@qq.com
     * @param o
     * @return boolean
     * @date 2019/1/6 19:46
     */
    private boolean isLeaf(T o) throws IllegalAccessException, InstantiationException {
        T temp=(T)o.getClass().newInstance();
        temp.setNodeFatherId(o.getId());
        List list=find(temp);
        return list!=null&&list.size()>0?false:true;
    }
    /**
     * 将缺少的父级加入
     * @author (作者) Dong Jie 154046519@qq.com
     * @param t
     * @param map
     * @param complete
     * @param o
     * @return void
     * @date 2019/1/6 19:40
     */
    private void addFather(T t, Map<Long,T> map,List<T> complete,T o) throws IllegalAccessException, InstantiationException {
        if(!map.containsKey(t.getNodeFatherId())&&!o.getNodeFatherId().equals(t.getNodeFatherId())){
            T father=(T)t.getClass().newInstance();
            father.setId(t.getNodeFatherId());
            father=findById(father);
            if(father!=null){
                map.put(father.getId(),father);
                complete.add(father);
                addFather(father,map,complete,o);
            }
        }
    }

    @Override
    public BasePage<T> buildLazyTree(T o, BasePage<T> page) throws IllegalAccessException, InstantiationException {
        page=findByPage(o,page);
        List<T> list= page.getRecords();
        List<T> complete=completeList(list,o);
        List<T> result=buildTree(complete,true);
        page.setRecords(result);
        return page;
    }
}
